#ifndef OPERATION_THREAD_H
#define OPERATION_THREAD_H

#include <QMutex>
#include <QPair>
#include <QQueue>
#include <QSQlDatabase>
#include <QThread>
#include <QWaitCondition>

#include "hbot_class.h"

class CBaseOperation;

typedef QPair<CBaseOperation *, void (*)(CBaseOperation *, QSqlDatabase *)> PairedOperation;

class CBaseOperation
{
protected:
	volatile bool m_Ready;

	unsigned int m_StartTicks;
	unsigned int m_EndTicks;

	QString m_Error;

	virtual void SetReady(bool ready)													{ m_Ready = ready; }

public:
	CBaseOperation(): m_Ready(false), m_StartTicks(0), m_EndTicks(0)					{ }
	virtual ~CBaseOperation();

	virtual bool GetReady()	const														{ return m_Ready; }
	virtual unsigned int GetElapsed() const												{ return m_Ready ? m_EndTicks - m_StartTicks : 0; }
	virtual QString GetError() const													{ return m_Error; }
};

class OperationQueue
{
private:
	QQueue<PairedOperation> m_OperationQueue;
	QMutex m_QueueMutex;
	QWaitCondition m_QueueNotEmpty;

public:
	OperationQueue();
	~OperationQueue();

	void Enqueue(CBaseOperation *opClass, void (*functPointer)(CBaseOperation *, QSqlDatabase *));
	PairedOperation Dequeue();
};

class OperationThread: public QThread
{
	Q_OBJECT

private:

	OperationQueue *m_Queue;
	QSqlDatabase m_Database;
	QString m_Error;
	QString m_ConnectionIdentifier;

public:
	OperationThread(const QString &connectionIndentifier, OperationQueue *queue, QThread::Priority priority, QObject *parent = 0);
	~OperationThread();

	void run();

signals:
	void ErrorChanged(const QString &error, const QString &databaseType, QString &connectionIdentifier);
};

void EnqueueOperation(CBaseOperation *opClass, void (*functPointer)(CBaseOperation *, QSqlDatabase *));

#endif // OPERATION_THREAD_H
